/*
 * @Author: 0x9DEFA478
 * @Date: 2025-08-02 17:14:10
 * @LastEditTime: 2025-09-15 23:32:32
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * 
 */
#include "HMakeTargetTask_Abstract.hpp"
#include "SystemProcessAuto.hpp"
#include "SystemUtility/C_VirtualTerminal_Macro.h"
#include "SystemUtility/C_iostream.hpp"
#include <sstream>




namespace HMake{
  
  TargetTask::TargetTask(const HMake::TargetConfig::ConstPointer& targetConfig,const std::string& shell,AttributeMask attribute)
    :targetConfig(targetConfig)
    ,attribute(attribute)
    ,postbuild(ReadCommand(targetConfig,"HMake.Target.PostBuild",shell))
    ,prebuild(ReadCommand(targetConfig,"HMake.Target.PreBuild",shell))
  {}

  int TargetTask::PreBuild(){
    int r=0;

    if(prebuild.size()<1){
      H::cout<<"无任务"<<std::endl;
      return r;
    }

    for(auto& Item:prebuild){
      r=RunPreProcess(Item);
      if(r!=0){
        break;
      }
    }

    return r;
  }


  void TargetTask::DisablePreBuild(){
    prebuild.clear();
  }

  void TargetTask::SetLogTag(std::string& RunLog,const std::string& RunLog_Initial,std::string& SkipLog,const std::string& SkipLog_Initial,const std::list<std::string> Args){
    RunLog=RunLog_Initial;
    if((attribute&AttributeMask::IsPrintSkip)!=0U){
      SkipLog=SkipLog_Initial;
    }
    if((attribute&AttributeMask::IsPrintArg)!=0U){
      auto argStr="\r\n"+StringListToString(Args);
      RunLog+=argStr;
      if(SkipLog.length()>0){
        SkipLog+=argStr;
      }
    }
  }

  void TargetTask::SetLogTag(std::string& RunLog,const std::string& RunLog_Initial,std::string& SkipLog,const std::string& SkipLog_Initial,const std::list<std::list<std::string>> ArgsList){
    RunLog=RunLog_Initial;
    if((attribute&AttributeMask::IsPrintSkip)!=0U){
      SkipLog=SkipLog_Initial;
    }
    if((attribute&AttributeMask::IsPrintArg)!=0U){
      for(auto& Item:ArgsList){
        auto argStr="\r\n\t"+StringListToString(Item);
        RunLog+=argStr;
        if(SkipLog.length()>0){
          SkipLog+=argStr;
        }
      }
    }
  }


  int TargetTask::RunPreProcess(const Value& arg){
    if((!arg.Valid())&&(arg.ValueArray().Length()<1)){
      return 0;
    }

    H::SystemProcess process;

    try{
      process.Run(arg.ValueArray(),false);
    }catch(const std::runtime_error& e){
      throw std::runtime_error("无法启动任务: "+arg.String()+" Error:"+e.what());
    }

    process.WaitStop();

    return process.GetResult();
  }


  std::string TargetTask::StringListToString(const std::list<std::string>& list){
    std::stringstream ss;

    for(auto& Item:list){
      ss<<" \e[" C_VT_Underline "m"<<Item<<"\e[0m";
    }
    return ss.str();
  }

  std::string TargetTask::ReadValue(const TargetConfig::ConstPointer& targetConfig,const std::string& ValueName){
    auto value=targetConfig->FindValue(ValueName);

    if((value==nullptr)||(value->IsNone())){
      throw std::runtime_error(ValueName+" 不存在");
    }

    if(!value->IsSingle()){
      throw std::runtime_error(ValueName+" 必须为单个值");
    }

    return value->ValueArray()[0];
  }

  std::string TargetTask::ReadValue_WithDefault(const TargetConfig::ConstPointer& targetConfig,const std::string& ValueName,const std::string& DefaultValue){
    auto value=targetConfig->FindValue(ValueName);

    if((value==nullptr)||(value->IsNone())){
      return DefaultValue;
    }

    if(!value->IsSingle()){
      throw std::runtime_error(ValueName+" 必须为单个值");
    }

    return value->ValueArray()[0];
  }

  std::string TargetTask::ReadValue_WithPathDefault(const TargetConfig::ConstPointer& targetConfig,const std::string& ValueName,const H::Path& Path,const std::string& cwd,const std::string& DefaultValue){
    auto Value=targetConfig->FindChildValue(ValueName,Path,cwd);
    if((!Value.empty())&&((*Value.begin())!=nullptr)&&((*Value.begin())->Valid())){
      auto& val=**Value.begin();
      
      if(!val.IsSingle()){
        throw std::runtime_error("${"+ValueName+",\""+Path.String()+"\"} 必须为单个值");
      }
      return val.ValueArray()[0];
    }
    return DefaultValue;
  }

  std::list<std::string> TargetTask::ReadValueArray(const TargetConfig::ConstPointer& targetConfig,const std::string& ValueName){
    std::list<std::string> r;

    auto value=targetConfig->FindValue(ValueName);
    if(value==nullptr){
      return r;
    }
    for(auto& Item:value->ValueArray()){
      r.emplace_back(Item);
    }
    return r;
  }

  std::list<std::string> TargetTask::ReadChildAllValue_WithPath(const TargetConfig::ConstPointer& targetConfig,const std::string& ValueName,const H::Path& Path,const std::string& cwd){
    std::list<std::string> r;
    auto ValueList=targetConfig->FindChildValue(ValueName,Path,cwd);

    for(auto& Value:ValueList){
      if(Value==nullptr){
        continue;
      }

      if(!Value->Valid()){
        continue;
      }

      std::list<std::string> list;
      for(auto& Item:Value->ValueArray()){
        list.emplace_back(Item);
      }

      if(list.empty()){
        continue;
      }

      r.splice(r.begin(),list);
    }

    return r;
  }

  std::list<Value> TargetTask::ReadCommand(const TargetConfig::ConstPointer& targetConfig,const std::string& ValueName,const std::string& shell){
    std::list<Value> r;
    
    std::string shellSuffix=shell;
    if(shellSuffix.length()>0){
      shellSuffix="."+shellSuffix;
    }
    
    const Value* vp;
    vp=targetConfig->FindValue(ValueName+shellSuffix);
    if((vp==nullptr)||(!vp->Valid())){
      return r;
    }

    for(auto& Item:vp->ValueArray()){
      if(Item.length()<1){
        continue;
      }
      vp=targetConfig->FindValue(Item);
      if(vp==nullptr){
        throw std::runtime_error("变量\""+ValueName+shellSuffix+"\"中用于指示命令的变量\""+Item+"\"不存在");
      }
      if(!vp->Valid()){
        continue;
      }
      
      r.emplace_back(*vp);
    }

    return r;
  }

}



